/* CsJni - .NET / Java Bridge
 * 
 * Copyright 2010 Robert E. Burke Licensed under the Apache License, Version 
 * 2.0 (the "License"); you may not use this file except in compliance with 
 * the License. You may obtain a copy of the License at 
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 
 * law or agreed to in writing, software distributed under the License is 
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 * KIND, either express or implied. See the License for the specific language 
 * governing permissions and limitations under the License. 
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace CsJni
{
    public sealed partial class JniEnvironment
    {
        internal class JniNativeInterface
        {
            #region Delegate Declarations

            // NOTE: The Java byte primitive is a signed byte, equivalent 
            // to sbyte in C#.  However, sbyte is not CLS Compliant, and 
            // almost all of the .NET Framework deals with unsigned bytes 
            // (the byte built-in type in C#).  So, decision was made that 
            // all the JNI wrappers which took Java bytes would be declared 
            // in C# as byte.  The bytes seem to be coerced between signed 
            // and unsigned correctly.

            // See class JBooleanConverter for handling of Java boolean type.

            // No way we can call methods using C/C++ elipses or va_list, so skip; 
            // luckily all such methods have a variant that takes "const jvalue * arguments"

            // Not going to use the following:
            // 1) UTF string methods, because Java and .NET both natively use Unicode
            // 2) CallNonvirtual<Type>Method methods - can think of no reason would 
            //      ever need these, particularly with C# proxies.
            // 3) Get<Type>ArrayElements and Release<Type>ArrayElements methods - 
            //      these access all the elements of an array, optionally modifying the 
            //      array.  Can use GetPrimitiveArrayCritical and GetStringCritical for 
            //      the same purpose, as long as we follow the JNI guidelines for using 
            //      these methods.
            // 4) NewWeakGlobalRef/DeleteWeakGlobalRef - dangerous, even though you can 
            //      check to see if the object has been garbage-collected, nothing to 
            //      to keep the gc thread from garbage collecting before you can actually 
            //      use it, inherent race condition. See 
            //      http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html#weak
            // 5) GetStringChars/ReleaseStringChars - return full content of a string, not 
            //      needed, we will use GetStringCritical/ReleaseStringCritical for that
            //      purpose, making sure to follow the JNI guidelines for those methods.
            //      Note that UTF versions of GetStringChars/ReleaseStringChars also 
            //      are excluded by general filter on all UTF string functions.

            // Removed (7 Dec 2006):
            // FatalError_Handler - just kill .Net process
            // EnsureLocalCapacity_Handler - poor way to do memory management
            // AllocObject_Handler - just use NewObject
            // UnregisterNatives_Handler - doubt would ever use
            // NewDirectByteBuffer_Handler - doubt would ever use
            // GetDirectBufferAddress_Handler - doubt would ever use
            // GetDirectBufferCapacity_Handler - doubt would ever use
            // ExceptionDescribe_Handler - wrote utility to extract as a string

            // Removed (14 Dec 2006)
            // FromReflectedField, ToReflectedField, 
            // FromReflectedMethod, ToReflectedMethod

            // Removed (3 May 2010)
            // DefineClass - needless complexity, a custom classloader with native method to get bytes would work better.

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int GetVersion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jclass */ IntPtr FindClass_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                [MarshalAs(UnmanagedType.LPStr)] string name
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jclass */ IntPtr GetSuperclass_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr subclassHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jboolean */ byte IsAssignableFrom_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr subclassHandle,
                /* jclass */ IntPtr superclassHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int Throw_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jthrowable */ IntPtr objectHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int ThrowNew_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                [MarshalAs(UnmanagedType.LPStr)] string message
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jthrowable */ IntPtr ExceptionOccurred_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void ExceptionClear_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int PushLocalFrame_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jint */ int capacity
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobject */ IntPtr PopLocalFrame_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr result
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobject */ IntPtr NewGlobalRef_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr localObjectHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void DeleteGlobalRef_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr globalObjectHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void DeleteLocalRef_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jboolean */ byte IsSameObject_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle1,
                /* jobject */ IntPtr objectHandle2
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobject */ IntPtr NewLocalRef_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobject */ IntPtr NewObjectA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jclass */ IntPtr GetObjectClass_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jboolean */ byte IsInstanceOf_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jclass */ IntPtr classHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jmethodID */ IntPtr GetMethodID_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                [MarshalAs(UnmanagedType.LPStr)] string name,
                [MarshalAs(UnmanagedType.LPStr)] string signature
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobject */ IntPtr CallObjectMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jboolean */ byte CallBooleanMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jbyte */ byte CallByteMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jchar */ char CallCharMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jshort */ short CallShortMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int CallIntMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jlong */ long CallLongMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jfloat */ float CallFloatMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jdouble */ double CallDoubleMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void CallVoidMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jfieldID */ IntPtr GetFieldID_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                [MarshalAs(UnmanagedType.LPStr)] string name,
                [MarshalAs(UnmanagedType.LPStr)] string signature
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobject */ IntPtr GetObjectField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jboolean */ byte GetBooleanField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jbyte */ byte GetByteField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jchar */ char GetCharField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jshort */ short GetShortField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int GetIntField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jlong */ long GetLongField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jfloat */ float GetFloatField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jdouble */ double GetDoubleField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetObjectField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jobject */ IntPtr @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetBooleanField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jboolean */ byte @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetByteField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jbyte */ byte @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetCharField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jchar */ char @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetShortField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jshort */ short @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetIntField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jint */ int @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetLongField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jlong */ long @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetFloatField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jfloat */ float @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetDoubleField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jdouble */ double @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jmethodID */ IntPtr GetStaticMethodID_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                [MarshalAs(UnmanagedType.LPStr)] string name,
                [MarshalAs(UnmanagedType.LPStr)] string signature
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobject */ IntPtr CallStaticObjectMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jboolean */ byte CallStaticBooleanMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jbyte */ byte CallStaticByteMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jchar */ char CallStaticCharMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jshort */ short CallStaticShortMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int CallStaticIntMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jlong */ long CallStaticLongMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jfloat */ float CallStaticFloatMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jdouble */ double CallStaticDoubleMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void CallStaticVoidMethodA_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jmethodID */ IntPtr methodId,
                /* const jvalue* */ JValue[] arguments
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jfieldID */ IntPtr GetStaticFieldID_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                [MarshalAs(UnmanagedType.LPStr)] string name,
                [MarshalAs(UnmanagedType.LPStr)] string signature
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobject */ IntPtr GetStaticObjectField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jboolean */ byte GetStaticBooleanField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jbyte */ byte GetStaticByteField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jchar */ char GetStaticCharField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jshort */ short GetStaticShortField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int GetStaticIntField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jlong */ long GetStaticLongField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jfloat */ float GetStaticFloatField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jdouble */ double GetStaticDoubleField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetStaticObjectField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jobject */ IntPtr value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetStaticBooleanField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jboolean */ byte value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetStaticByteField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jbyte */ byte value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetStaticCharField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jchar */ char value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetStaticShortField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jshort */ short value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetStaticIntField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jint */ int value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetStaticLongField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jlong */ long value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetStaticFloatField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jfloat */ float value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetStaticDoubleField_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* jfieldID */ IntPtr fieldId,
                /* jdouble */ double value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jstring */ IntPtr NewString_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* const jchar* */ [MarshalAs(UnmanagedType.LPWStr)] string unicode,
                /* jsize */ int length
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jsize */ int GetStringLength_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jstring */ IntPtr stringHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jsize */ int GetArrayLength_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jarray */ IntPtr array
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobjectArray */ IntPtr NewObjectArray_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jsize */ int length,
                /* jclass */ IntPtr classHandle,
                /* jobject */ IntPtr init
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jobject */ IntPtr GetObjectArrayElement_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobjectArray */ IntPtr array,
                /* jsize */ int index
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetObjectArrayElement_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobjectArray */ IntPtr array,
                /* jsize */ int index,
                /* jobject */ IntPtr @value
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jbooleanArray */ IntPtr NewBooleanArray_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jsize */ int length
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jbyteArray */ IntPtr NewByteArray_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jsize */ int length
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jcharArray */ IntPtr NewCharArray_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jsize */ int length
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jshortArray */ IntPtr NewShortArray_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jsize */ int length
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jintArray */ IntPtr NewIntArray_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jsize */ int length
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jlongArray */ IntPtr NewLongArray_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jsize */ int length
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jfloatArray */ IntPtr NewFloatArray_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jsize */ int length
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jdoubleArray */ IntPtr NewDoubleArray_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jsize */ int length
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void GetBooleanArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jbooleanArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* jboolean* */ [Out] byte[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void GetByteArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jbyteArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* jbyte* */ [Out] byte[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void GetCharArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jcharArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* jchar* */ [Out] char[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void GetShortArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jshortArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* jshort* */ [Out] short[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void GetIntArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jintArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* jint* */ [Out] int[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void GetLongArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jlongArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* jlong* */ [Out] long[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void GetFloatArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jfloatArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* jfloat* */ [Out] float[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void GetDoubleArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jdoubleArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* jdouble* */ [Out] double[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetBooleanArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jbooleanArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* const jboolean* */ byte[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetByteArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jbyteArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* const jbyte* */ byte[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetCharArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jcharArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* const jchar* */ char[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetShortArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jshortArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* const jshort* */ short[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetIntArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jintArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* const jint* */ int[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetLongArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jlongArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* const jlong* */ long[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetFloatArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jfloatArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* const jfloat* */ float[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void SetDoubleArrayRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jdoubleArray */ IntPtr array,
                /* jsize */ int start,
                /* jsize */ int length,
                /* const jdouble* */ double[] buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int RegisterNatives_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jclass */ IntPtr classHandle,
                /* const JNINativeMethod* */ JniNativeMethod[] methods,
                /* jint */ int nMethods
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int MonitorEnter_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int MonitorExit_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jobject */ IntPtr objectHandle
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public unsafe delegate /* jint */ int GetJavaVM_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* JavaVM** */ void*** vm
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate void GetStringRegion_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jstring */ IntPtr stringHandle,
                /* jsize */ int start,
                /* jsize */ int length,
                [MarshalAs(UnmanagedType.LPWStr)] StringBuilder buffer
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public unsafe delegate void* GetPrimitiveArrayCritical_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jarray */ IntPtr array,
                /* jboolean* */ byte* isCopy
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public unsafe delegate void ReleasePrimitiveArrayCritical_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jarray */ IntPtr array,
                void* carray,
                /* jint */ int mode
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public unsafe delegate /* const jchar* */ char* GetStringCritical_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jstring */ IntPtr stringHandle,
                /* jboolean* */ byte* isCopy
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public unsafe delegate void ReleaseStringCritical_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle,
                /* jstring */ IntPtr stringHandle,
                /* const jchar* */ char* cstring
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jboolean */ byte ExceptionCheck_Handler(
                /* JNIEnv* */ IntPtr threadEnvironmentHandle
                );


            // The remainder of JNI Methods are for JNI_VERSION_1_4 or higher, 
            // corresponding delegates will be null

            #endregion Delegate Declarations

            #region Delegate Fields

            public GetVersion_Handler GetVersion;
            public FindClass_Handler FindClass;
            public GetSuperclass_Handler GetSuperclass;
            public IsAssignableFrom_Handler IsAssignableFrom;
            public Throw_Handler Throw;
            public ThrowNew_Handler ThrowNew;
            public ExceptionOccurred_Handler ExceptionOccurred;
            public ExceptionClear_Handler ExceptionClear;
            public PushLocalFrame_Handler PushLocalFrame;
            public PopLocalFrame_Handler PopLocalFrame;
            public NewGlobalRef_Handler NewGlobalRef;
            public DeleteGlobalRef_Handler DeleteGlobalRef;
            public DeleteLocalRef_Handler DeleteLocalRef;
            public IsSameObject_Handler IsSameObject;
            public NewLocalRef_Handler NewLocalRef;
            public NewObjectA_Handler NewObjectA;
            public GetObjectClass_Handler GetObjectClass;
            public IsInstanceOf_Handler IsInstanceOf;
            public GetMethodID_Handler GetMethodID;
            public CallObjectMethodA_Handler CallObjectMethodA;
            public CallBooleanMethodA_Handler CallBooleanMethodA;
            public CallByteMethodA_Handler CallByteMethodA;
            public CallCharMethodA_Handler CallCharMethodA;
            public CallShortMethodA_Handler CallShortMethodA;
            public CallIntMethodA_Handler CallIntMethodA;
            public CallLongMethodA_Handler CallLongMethodA;
            public CallFloatMethodA_Handler CallFloatMethodA;
            public CallDoubleMethodA_Handler CallDoubleMethodA;
            public CallVoidMethodA_Handler CallVoidMethodA;
            public GetFieldID_Handler GetFieldID;
            public GetObjectField_Handler GetObjectField;
            public GetBooleanField_Handler GetBooleanField;
            public GetByteField_Handler GetByteField;
            public GetCharField_Handler GetCharField;
            public GetShortField_Handler GetShortField;
            public GetIntField_Handler GetIntField;
            public GetLongField_Handler GetLongField;
            public GetFloatField_Handler GetFloatField;
            public GetDoubleField_Handler GetDoubleField;
            public SetObjectField_Handler SetObjectField;
            public SetBooleanField_Handler SetBooleanField;
            public SetByteField_Handler SetByteField;
            public SetCharField_Handler SetCharField;
            public SetShortField_Handler SetShortField;
            public SetIntField_Handler SetIntField;
            public SetLongField_Handler SetLongField;
            public SetFloatField_Handler SetFloatField;
            public SetDoubleField_Handler SetDoubleField;
            public GetStaticMethodID_Handler GetStaticMethodID;
            public CallStaticObjectMethodA_Handler CallStaticObjectMethodA;
            public CallStaticBooleanMethodA_Handler CallStaticBooleanMethodA;
            public CallStaticByteMethodA_Handler CallStaticByteMethodA;
            public CallStaticCharMethodA_Handler CallStaticCharMethodA;
            public CallStaticShortMethodA_Handler CallStaticShortMethodA;
            public CallStaticIntMethodA_Handler CallStaticIntMethodA;
            public CallStaticLongMethodA_Handler CallStaticLongMethodA;
            public CallStaticFloatMethodA_Handler CallStaticFloatMethodA;
            public CallStaticDoubleMethodA_Handler CallStaticDoubleMethodA;
            public CallStaticVoidMethodA_Handler CallStaticVoidMethodA;
            public GetStaticFieldID_Handler GetStaticFieldID;
            public GetStaticObjectField_Handler GetStaticObjectField;
            public GetStaticBooleanField_Handler GetStaticBooleanField;
            public GetStaticByteField_Handler GetStaticByteField;
            public GetStaticCharField_Handler GetStaticCharField;
            public GetStaticShortField_Handler GetStaticShortField;
            public GetStaticIntField_Handler GetStaticIntField;
            public GetStaticLongField_Handler GetStaticLongField;
            public GetStaticFloatField_Handler GetStaticFloatField;
            public GetStaticDoubleField_Handler GetStaticDoubleField;
            public SetStaticObjectField_Handler SetStaticObjectField;
            public SetStaticBooleanField_Handler SetStaticBooleanField;
            public SetStaticByteField_Handler SetStaticByteField;
            public SetStaticCharField_Handler SetStaticCharField;
            public SetStaticShortField_Handler SetStaticShortField;
            public SetStaticIntField_Handler SetStaticIntField;
            public SetStaticLongField_Handler SetStaticLongField;
            public SetStaticFloatField_Handler SetStaticFloatField;
            public SetStaticDoubleField_Handler SetStaticDoubleField;
            public NewString_Handler NewString;
            public GetStringLength_Handler GetStringLength;
            public GetArrayLength_Handler GetArrayLength;
            public NewObjectArray_Handler NewObjectArray;
            public GetObjectArrayElement_Handler GetObjectArrayElement;
            public SetObjectArrayElement_Handler SetObjectArrayElement;
            public NewBooleanArray_Handler NewBooleanArray;
            public NewByteArray_Handler NewByteArray;
            public NewCharArray_Handler NewCharArray;
            public NewShortArray_Handler NewShortArray;
            public NewIntArray_Handler NewIntArray;
            public NewLongArray_Handler NewLongArray;
            public NewFloatArray_Handler NewFloatArray;
            public NewDoubleArray_Handler NewDoubleArray;
            public GetBooleanArrayRegion_Handler GetBooleanArrayRegion;
            public GetByteArrayRegion_Handler GetByteArrayRegion;
            public GetCharArrayRegion_Handler GetCharArrayRegion;
            public GetShortArrayRegion_Handler GetShortArrayRegion;
            public GetIntArrayRegion_Handler GetIntArrayRegion;
            public GetLongArrayRegion_Handler GetLongArrayRegion;
            public GetFloatArrayRegion_Handler GetFloatArrayRegion;
            public GetDoubleArrayRegion_Handler GetDoubleArrayRegion;
            public SetBooleanArrayRegion_Handler SetBooleanArrayRegion;
            public SetByteArrayRegion_Handler SetByteArrayRegion;
            public SetCharArrayRegion_Handler SetCharArrayRegion;
            public SetShortArrayRegion_Handler SetShortArrayRegion;
            public SetIntArrayRegion_Handler SetIntArrayRegion;
            public SetLongArrayRegion_Handler SetLongArrayRegion;
            public SetFloatArrayRegion_Handler SetFloatArrayRegion;
            public SetDoubleArrayRegion_Handler SetDoubleArrayRegion;
            public RegisterNatives_Handler RegisterNatives;
            public MonitorEnter_Handler MonitorEnter;
            public MonitorExit_Handler MonitorExit;
            public GetJavaVM_Handler GetJavaVM;
            public GetStringRegion_Handler GetStringRegion;
            public GetPrimitiveArrayCritical_Handler GetPrimitiveArrayCritical;
            public ReleasePrimitiveArrayCritical_Handler ReleasePrimitiveArrayCritical;
            public GetStringCritical_Handler GetStringCritical;
            public ReleaseStringCritical_Handler ReleaseStringCritical;
            public ExceptionCheck_Handler ExceptionCheck;

            // The remainder of JNI Methods are for JNI_VERSION_1_4 or higher, 
            // corresponding delegates will be null

            #endregion Delegate Fields 

            public JniNativeInterface(IntPtr environmentHandle, JniVersion jniVersion)
            {
                IntPtr functionTableBaseAddress = Marshal.ReadIntPtr(environmentHandle);
                int countFunctionPointers = 232; // for JniVersion.Version1Minor4
                if (jniVersion == JniVersion.Version1Minor2)
                {
                    countFunctionPointers = 229;
                }
                IntPtr[] functionTable = new IntPtr[countFunctionPointers];
                Marshal.Copy(functionTableBaseAddress, functionTable, 0, functionTable.Length);
                Init(functionTable, jniVersion);
            }

            private static T GetDel<T>(IntPtr functionPointer)
            {
                return (T)(object)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(T));
            }

            private unsafe void Init(IntPtr[] functionTable, JniVersion jniVersion)
            {
                #region Delegate Initialization

                this.GetVersion = GetDel<GetVersion_Handler>(functionTable[4]); 
                this.FindClass = GetDel<FindClass_Handler>(functionTable[6]); 
                this.GetSuperclass = GetDel<GetSuperclass_Handler>(functionTable[10]); 
                this.IsAssignableFrom = GetDel<IsAssignableFrom_Handler>(functionTable[11]); 
                this.Throw = GetDel<Throw_Handler>(functionTable[13]); 
                this.ThrowNew = GetDel<ThrowNew_Handler>(functionTable[14]); 
                this.ExceptionOccurred = GetDel<ExceptionOccurred_Handler>(functionTable[15]); 
                this.ExceptionClear = GetDel<ExceptionClear_Handler>(functionTable[17]); 
                this.PushLocalFrame = GetDel<PushLocalFrame_Handler>(functionTable[19]); 
                this.PopLocalFrame = GetDel<PopLocalFrame_Handler>(functionTable[20]); 
                this.NewGlobalRef = GetDel<NewGlobalRef_Handler>(functionTable[21]); 
                this.DeleteGlobalRef = GetDel<DeleteGlobalRef_Handler>(functionTable[22]); 
                this.DeleteLocalRef = GetDel<DeleteLocalRef_Handler>(functionTable[23]); 
                this.IsSameObject = GetDel<IsSameObject_Handler>(functionTable[24]); 
                this.NewLocalRef = GetDel<NewLocalRef_Handler>(functionTable[25]); 
                this.NewObjectA = GetDel<NewObjectA_Handler>(functionTable[30]); 
                this.GetObjectClass = GetDel<GetObjectClass_Handler>(functionTable[31]); 
                this.IsInstanceOf = GetDel<IsInstanceOf_Handler>(functionTable[32]); 
                this.GetMethodID = GetDel<GetMethodID_Handler>(functionTable[33]); 
                this.CallObjectMethodA = GetDel<CallObjectMethodA_Handler>(functionTable[36]); 
                this.CallBooleanMethodA = GetDel<CallBooleanMethodA_Handler>(functionTable[39]); 
                this.CallByteMethodA = GetDel<CallByteMethodA_Handler>(functionTable[42]); 
                this.CallCharMethodA = GetDel<CallCharMethodA_Handler>(functionTable[45]); 
                this.CallShortMethodA = GetDel<CallShortMethodA_Handler>(functionTable[48]); 
                this.CallIntMethodA = GetDel<CallIntMethodA_Handler>(functionTable[51]); 
                this.CallLongMethodA = GetDel<CallLongMethodA_Handler>(functionTable[54]); 
                this.CallFloatMethodA = GetDel<CallFloatMethodA_Handler>(functionTable[57]); 
                this.CallDoubleMethodA = GetDel<CallDoubleMethodA_Handler>(functionTable[60]); 
                this.CallVoidMethodA = GetDel<CallVoidMethodA_Handler>(functionTable[63]); 
                this.GetFieldID = GetDel<GetFieldID_Handler>(functionTable[94]); 
                this.GetObjectField = GetDel<GetObjectField_Handler>(functionTable[95]); 
                this.GetBooleanField = GetDel<GetBooleanField_Handler>(functionTable[96]); 
                this.GetByteField = GetDel<GetByteField_Handler>(functionTable[97]); 
                this.GetCharField = GetDel<GetCharField_Handler>(functionTable[98]); 
                this.GetShortField = GetDel<GetShortField_Handler>(functionTable[99]); 
                this.GetIntField = GetDel<GetIntField_Handler>(functionTable[100]); 
                this.GetLongField = GetDel<GetLongField_Handler>(functionTable[101]); 
                this.GetFloatField = GetDel<GetFloatField_Handler>(functionTable[102]); 
                this.GetDoubleField = GetDel<GetDoubleField_Handler>(functionTable[103]); 
                this.SetObjectField = GetDel<SetObjectField_Handler>(functionTable[104]); 
                this.SetBooleanField = GetDel<SetBooleanField_Handler>(functionTable[105]); 
                this.SetByteField = GetDel<SetByteField_Handler>(functionTable[106]); 
                this.SetCharField = GetDel<SetCharField_Handler>(functionTable[107]); 
                this.SetShortField = GetDel<SetShortField_Handler>(functionTable[108]); 
                this.SetIntField = GetDel<SetIntField_Handler>(functionTable[109]); 
                this.SetLongField = GetDel<SetLongField_Handler>(functionTable[110]); 
                this.SetFloatField = GetDel<SetFloatField_Handler>(functionTable[111]); 
                this.SetDoubleField = GetDel<SetDoubleField_Handler>(functionTable[112]); 
                this.GetStaticMethodID = GetDel<GetStaticMethodID_Handler>(functionTable[113]); 
                this.CallStaticObjectMethodA = GetDel<CallStaticObjectMethodA_Handler>(functionTable[116]); 
                this.CallStaticBooleanMethodA = GetDel<CallStaticBooleanMethodA_Handler>(functionTable[119]); 
                this.CallStaticByteMethodA = GetDel<CallStaticByteMethodA_Handler>(functionTable[122]); 
                this.CallStaticCharMethodA = GetDel<CallStaticCharMethodA_Handler>(functionTable[125]); 
                this.CallStaticShortMethodA = GetDel<CallStaticShortMethodA_Handler>(functionTable[128]); 
                this.CallStaticIntMethodA = GetDel<CallStaticIntMethodA_Handler>(functionTable[131]); 
                this.CallStaticLongMethodA = GetDel<CallStaticLongMethodA_Handler>(functionTable[134]); 
                this.CallStaticFloatMethodA = GetDel<CallStaticFloatMethodA_Handler>(functionTable[137]); 
                this.CallStaticDoubleMethodA = GetDel<CallStaticDoubleMethodA_Handler>(functionTable[140]); 
                this.CallStaticVoidMethodA = GetDel<CallStaticVoidMethodA_Handler>(functionTable[143]); 
                this.GetStaticFieldID = GetDel<GetStaticFieldID_Handler>(functionTable[144]); 
                this.GetStaticObjectField = GetDel<GetStaticObjectField_Handler>(functionTable[145]); 
                this.GetStaticBooleanField = GetDel<GetStaticBooleanField_Handler>(functionTable[146]); 
                this.GetStaticByteField = GetDel<GetStaticByteField_Handler>(functionTable[147]); 
                this.GetStaticCharField = GetDel<GetStaticCharField_Handler>(functionTable[148]); 
                this.GetStaticShortField = GetDel<GetStaticShortField_Handler>(functionTable[149]); 
                this.GetStaticIntField = GetDel<GetStaticIntField_Handler>(functionTable[150]); 
                this.GetStaticLongField = GetDel<GetStaticLongField_Handler>(functionTable[151]); 
                this.GetStaticFloatField = GetDel<GetStaticFloatField_Handler>(functionTable[152]); 
                this.GetStaticDoubleField = GetDel<GetStaticDoubleField_Handler>(functionTable[153]); 
                this.SetStaticObjectField = GetDel<SetStaticObjectField_Handler>(functionTable[154]); 
                this.SetStaticBooleanField = GetDel<SetStaticBooleanField_Handler>(functionTable[155]); 
                this.SetStaticByteField = GetDel<SetStaticByteField_Handler>(functionTable[156]); 
                this.SetStaticCharField = GetDel<SetStaticCharField_Handler>(functionTable[157]); 
                this.SetStaticShortField = GetDel<SetStaticShortField_Handler>(functionTable[158]); 
                this.SetStaticIntField = GetDel<SetStaticIntField_Handler>(functionTable[159]); 
                this.SetStaticLongField = GetDel<SetStaticLongField_Handler>(functionTable[160]); 
                this.SetStaticFloatField = GetDel<SetStaticFloatField_Handler>(functionTable[161]); 
                this.SetStaticDoubleField = GetDel<SetStaticDoubleField_Handler>(functionTable[162]); 
                this.NewString = GetDel<NewString_Handler>(functionTable[163]); 
                this.GetStringLength = GetDel<GetStringLength_Handler>(functionTable[164]); 
                this.GetArrayLength = GetDel<GetArrayLength_Handler>(functionTable[171]); 
                this.NewObjectArray = GetDel<NewObjectArray_Handler>(functionTable[172]); 
                this.GetObjectArrayElement = GetDel<GetObjectArrayElement_Handler>(functionTable[173]); 
                this.SetObjectArrayElement = GetDel<SetObjectArrayElement_Handler>(functionTable[174]); 
                this.NewBooleanArray = GetDel<NewBooleanArray_Handler>(functionTable[175]); 
                this.NewByteArray = GetDel<NewByteArray_Handler>(functionTable[176]); 
                this.NewCharArray = GetDel<NewCharArray_Handler>(functionTable[177]); 
                this.NewShortArray = GetDel<NewShortArray_Handler>(functionTable[178]); 
                this.NewIntArray = GetDel<NewIntArray_Handler>(functionTable[179]); 
                this.NewLongArray = GetDel<NewLongArray_Handler>(functionTable[180]); 
                this.NewFloatArray = GetDel<NewFloatArray_Handler>(functionTable[181]); 
                this.NewDoubleArray = GetDel<NewDoubleArray_Handler>(functionTable[182]); 
                this.GetBooleanArrayRegion = GetDel<GetBooleanArrayRegion_Handler>(functionTable[199]); 
                this.GetByteArrayRegion = GetDel<GetByteArrayRegion_Handler>(functionTable[200]); 
                this.GetCharArrayRegion = GetDel<GetCharArrayRegion_Handler>(functionTable[201]); 
                this.GetShortArrayRegion = GetDel<GetShortArrayRegion_Handler>(functionTable[202]); 
                this.GetIntArrayRegion = GetDel<GetIntArrayRegion_Handler>(functionTable[203]); 
                this.GetLongArrayRegion = GetDel<GetLongArrayRegion_Handler>(functionTable[204]); 
                this.GetFloatArrayRegion = GetDel<GetFloatArrayRegion_Handler>(functionTable[205]); 
                this.GetDoubleArrayRegion = GetDel<GetDoubleArrayRegion_Handler>(functionTable[206]); 
                this.SetBooleanArrayRegion = GetDel<SetBooleanArrayRegion_Handler>(functionTable[207]); 
                this.SetByteArrayRegion = GetDel<SetByteArrayRegion_Handler>(functionTable[208]); 
                this.SetCharArrayRegion = GetDel<SetCharArrayRegion_Handler>(functionTable[209]); 
                this.SetShortArrayRegion = GetDel<SetShortArrayRegion_Handler>(functionTable[210]); 
                this.SetIntArrayRegion = GetDel<SetIntArrayRegion_Handler>(functionTable[211]); 
                this.SetLongArrayRegion = GetDel<SetLongArrayRegion_Handler>(functionTable[212]); 
                this.SetFloatArrayRegion = GetDel<SetFloatArrayRegion_Handler>(functionTable[213]); 
                this.SetDoubleArrayRegion = GetDel<SetDoubleArrayRegion_Handler>(functionTable[214]); 
                this.RegisterNatives = GetDel<RegisterNatives_Handler>(functionTable[215]); 
                this.MonitorEnter = GetDel<MonitorEnter_Handler>(functionTable[217]); 
                this.MonitorExit = GetDel<MonitorExit_Handler>(functionTable[218]); 
                this.GetJavaVM = GetDel<GetJavaVM_Handler>(functionTable[219]); 
                this.GetStringRegion = GetDel<GetStringRegion_Handler>(functionTable[220]); 
                this.GetPrimitiveArrayCritical = GetDel<GetPrimitiveArrayCritical_Handler>(functionTable[222]); 
                this.ReleasePrimitiveArrayCritical = GetDel<ReleasePrimitiveArrayCritical_Handler>(functionTable[223]); 
                this.GetStringCritical = GetDel<GetStringCritical_Handler>(functionTable[224]); 
                this.ReleaseStringCritical = GetDel<ReleaseStringCritical_Handler>(functionTable[225]); 
                this.ExceptionCheck = GetDel<ExceptionCheck_Handler>(functionTable[228]); 


                // The remainder of JNI Methods are for JNI_VERSION_1_4 or higher, 
                // corresponding delegates will be null

                if (jniVersion == JniVersion.Version1Minor2)
                {
                    return;
                }

                #endregion Delegate Initialization
            }
        }
    }
}
